home *** CD-ROM | disk | FTP | other *** search
- /*
- File: VideoFrameToGWorld.c
-
- Description: VideoFrameToGWorld is an example of decompressing frames from a video track
- into an offscreen buffer so the pixels can be manipulated at a later time.
-
- Author: era based on code provided by Kevin Marks
-
- Copyright: © Copyright 2000 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Change History (most recent first): <1> 4/1/00 initial release
-
- */
-
- #include "VideoFrameToGWorld.h"
-
- // Globals
- //------------------------------------------------------------------------------
- WindowRef gWindow = NULL;
- GWorldPtr gSrcGWorld = NULL;
- Movie gMovie = NULL;
- TimeValue gMovieTime = 0; // set current time value to begining of the Movie
- UInt32 gFrameCount = -1;
- UInt32 gFrameNumber = 0;
- Rect gMovieBox;
-
- //------------------------------------------------------------------------------
- // Open up the Movie file and get a Movie from it.
- //------------------------------------------------------------------------------
- void OpenMovie( void )
- {
- FSSpec theFSSpec;
- short refnum = 0;
- OSType openTypeList[] = {kQTFileTypeMovie};
- short numTypes = 1;
-
- OSErr err = noErr;
-
- err = GetOneFileWithPreview(numTypes, openTypeList, &theFSSpec, NULL);
- BailError(err);
-
- // open a Movie file using the FSSpec and create a Movie from that file.
- err = OpenMovieFile(&theFSSpec, &refnum, fsRdPerm);
- BailError(err);
-
- NewMovieFromFile(&gMovie, refnum, NULL, NULL, newMovieActive, NULL);
-
- bail:
- // we're done with the file.
- if (refnum)
- CloseMovieFile(refnum);
- }
-
- //------------------------------------------------------------------------------
- // Count the number of video "frames" in the Movie by stepping through
- // all of the video "interesting times", or in other words, the places where the
- // movie displays a new video sample. The time between these interesting times
- // is not necessarily constant.
- //------------------------------------------------------------------------------
- void CountThemFrames( void )
- {
- OSType whichMediaType = VIDEO_TYPE;
- short flags = nextTimeMediaSample + nextTimeEdgeOK;
- TimeValue duration;
- TimeValue theTime = 0;
-
- while (theTime >= 0) {
- gFrameCount++;
- GetMovieNextInterestingTime(gMovie,
- flags,
- 1,
- &whichMediaType,
- theTime,
- 0,
- &theTime,
- &duration);
-
- // after the first interesting time, don't include the time we
- // are currently at.
-
- flags = nextTimeMediaSample;
- } // while
- }
-
- //------------------------------------------------------------------------------
- // Get the bounding rectangle of the Movie the create a 32-bit GWorld
- // with those dimensions.
- // This GWorld will be used for rendering Movie frames into.
- //------------------------------------------------------------------------------
- void MakeGWorld( void )
- {
- Rect srcRect;
- Rect portRect;
- RGBColor theBlackColor = { 0, 0, 0 };
- RGBColor theWhiteColor = { 65535, 65535, 65535 };
-
- OSErr err = noErr;
-
- GetMovieBox(gMovie,&srcRect);
-
- err = NewGWorld(&gSrcGWorld,
- k32ARGBPixelFormat,
- &srcRect,
- NULL,
- NULL,
- 0);
- BailError(err);
-
- LockPixels(GetGWorldPixMap(gSrcGWorld));
-
- SetGWorld(gSrcGWorld,NULL);
- GetPortBounds(gSrcGWorld, &portRect);
- RGBBackColor(&theBlackColor);
- RGBForeColor(&theWhiteColor);
- EraseRect(&portRect);
-
- bail:
- return;
- }
-
- //------------------------------------------------------------------------------
- // Blit the contents of the GWorld to the window
- //------------------------------------------------------------------------------
- void BlitToScreen( void )
- {
- Rect srcRect;
- Rect destRect;
-
- GetPortBounds(gSrcGWorld, &srcRect);
- GetPortBounds(GetWindowPort(gWindow), &destRect);
- CopyBits(GetPortBitMapForCopyBits(gSrcGWorld),
- GetPortBitMapForCopyBits(GetWindowPort(gWindow)),
- &srcRect,
- &destRect,
- srcCopy,
- NULL);
- }
-
- //------------------------------------------------------------------------------
- // First get the next frame of the movie, set the movie time for that frame,
- // then task the movie which will draw the frame to the GWorld
- // Modify the movie matrix so the next frame will be rotated just for fun and
- // finally draw the frame number on top of the image and inval the window rect
- //------------------------------------------------------------------------------
- void NextFrame( void )
- {
- CGrafPtr savedPort;
- GDHandle savedDevice;
- Rect theRect;
- char frame[32];
- Str255 theString;
- Rect invalRect;
- MatrixRecord theMovieMatrix;
-
- // these don't change, always rotate 30 degrees anchored in
- // the center of the frame
- static Fixed degrees = Long2Fix(30);
- static Fixed x = Long2Fix((gMovieBox.right - gMovieBox.left) / 2);
- static Fixed y = Long2Fix((gMovieBox.bottom - gMovieBox.top) / 2);
-
- if ( gFrameNumber < gFrameCount ) {
-
- TimeValue duration;
-
- GetGWorld(&savedPort, &savedDevice);
- SetGWorld(gSrcGWorld, NULL);
-
- // get the next frame of the source movie
- short flags = nextTimeMediaSample;
- OSType whichMediaType = VIDEO_TYPE;
-
- // if this is the first frame, include the frame we are currently on
- if (gFrameNumber == 0)
- flags |= nextTimeEdgeOK;
-
- // skip to the next interesting time and get the duration for that frame
- GetMovieNextInterestingTime(gMovie,
- flags,
- 1,
- &whichMediaType,
- gMovieTime,
- 0,
- &gMovieTime,
- &duration);
-
- // set the time for the frame and give time to the movie toolbox
- SetMovieTimeValue(gMovie,gMovieTime);
- GetPortBounds(gSrcGWorld, &theRect);
- EraseRect(&theRect); // paint the background black
-
- // *** this does the actual drawing into the GWorld ***
- MoviesTask(gMovie,0);
-
- //------------------------------------------------------------------------------
- // You now have pixels you can play with in the GWorld!
- // This sample simply blits the contents of the GWorld back to
- // a window with the frame number drawn on top of the image
- //------------------------------------------------------------------------------
-
- // have some fun and rotate the movie frame
- GetMovieMatrix(gMovie, &theMovieMatrix);
- RotateMatrix(&theMovieMatrix, degrees, x, y);
- SetMovieMatrix(gMovie, &theMovieMatrix);
-
- gFrameNumber++;
-
- // draw the frame number on top of the image
- TextSize(12);
- TextMode(srcCopy);
- MoveTo( theRect.left + 5, theRect.bottom - 15 );
- sprintf(frame,"Frame #%ld",gFrameNumber);
- CopyCStringToPascal(frame, theString);
- DrawString(theString);
-
- SetGWorld(savedPort, savedDevice);
-
- // inval the window to generate an update event
- GetPort(&savedPort);
- SetPortWindowPort(gWindow);
-
- GetWindowBounds(gWindow, kWindowContentRgn, &invalRect);
- GlobalToLocal( (Point *)&invalRect.top);
- InvalWindowRect(gWindow, &invalRect);
-
- SetPort(savedPort);
-
- } else {
- // reset the movie time back to the beginning
- // then do it all over again
- gMovieTime = 0;
- gFrameNumber = 0;
- NextFrame();
- }
- }
-
- int main()
- {
- Rect rectWnd;
- Rect rectMovie;
- WindowRef pWhichWindow;
- short nPart;
- EventRecord theEvent;
- Boolean bDone = false;
-
- OSErr result = noErr;
-
- // initialize for Carbon and QuickTime
- InitCursor();
- result = EnterMovies();
- BailError(result);
-
- // create the window
- SetRect(&rectWnd, 100, 100, 200, 200);
- gWindow = NewCWindow(NULL, &rectWnd, "\pVideoFrameToGworld", false, kWindowDocumentProc, (WindowPtr)-1, true, NULL);
- BailNULL(gWindow);
- SetPortWindowPort(gWindow);
-
- // get the movie
- OpenMovie();
- BailNULL(gMovie);
-
- // normalize the movie rect
- GetMovieBox(gMovie, &rectMovie);
- OffsetRect(&rectMovie, -rectMovie.left, -rectMovie.top);
- SetMovieBox(gMovie, &rectMovie);
- gMovieBox = rectMovie;
-
- SizeWindow(gWindow, rectMovie.right, rectMovie.bottom, true);
- ShowWindow(gWindow);
-
- CountThemFrames();
-
- // create the offscreen to draw into
- MakeGWorld();
- BailNULL(gSrcGWorld);
-
- // *** set the graphics world for displaying the movie ***
- SetMovieGWorld(gMovie, gSrcGWorld, GetGWorldDevice(gSrcGWorld));
-
- // get the first frame
- NextFrame();
-
- while (!bDone) {
- if (WaitNextEvent(everyEvent, &theEvent, 0, NULL)) {
- switch (theEvent.what) {
- case updateEvt:
- pWhichWindow = (WindowPtr)theEvent.message;
- if (pWhichWindow == gWindow) {
- // draw the frame
- GrafPtr savedPort;
- CGrafPtr windowPort = GetWindowPort(pWhichWindow);
- RgnHandle vizRgn = NewRgn();
- RgnHandle savedClip = NewRgn();
-
- GetPort(&savedPort);
- SetPort(windowPort);
- GetClip(savedClip);
-
- BeginUpdate(pWhichWindow);
- GetPortVisibleRegion(windowPort, vizRgn);
- SetClip(vizRgn);
- BlitToScreen();
- EndUpdate(pWhichWindow);
-
- SetClip(savedClip);
- SetPort(savedPort);
- DisposeRgn(savedClip);
- DisposeRgn(vizRgn);
- }
- break;
-
- case mouseDown:
- nPart = FindWindow(theEvent.where, &pWhichWindow);
- if (pWhichWindow == gWindow) {
- switch (nPart) {
- case inGoAway:
- // we're done
- bDone = TrackGoAway(pWhichWindow, theEvent.where);
- break;
-
- case inContent:
- // get the next frame
- NextFrame();
- break;
-
- case inDrag:
- BitMap screenBits;
- GetQDGlobalsScreenBits(&screenBits);
- DragWindow(pWhichWindow, theEvent.where, &screenBits.bounds);
- break;
- } // switch
- }
- break;
- } // switch
- }
- } // while
-
- bail:
- if ( gMovie )
- DisposeMovie(gMovie);
-
- if ( gWindow )
- DisposeWindow(gWindow);
- }